#pragma once

#include <memory>
#include <opencv2/core.hpp>
#include "common.h"
#include "camera.h"

class Body;
class Camera;

class Render {
public:
	virtual ~Render() {}

	virtual bool AddBody(Body* body_ptr) = 0;
	virtual bool DeleteBody(Body* body_ptr) = 0;

	virtual bool RenderSilhouette() = 0;
	virtual bool RenderNormal() = 0;
	
	virtual float Depth(ushort depth_image_value) const = 0;
	virtual float Depth(const cv::Point2i & image_coordinate) const = 0;
	virtual Eigen::Vector3f PointVector(const cv::Point2i& image_coordinate) const = 0;

	virtual bool FetchDepthImage() = 0;
	virtual bool FetchNormalImage() = 0;
	virtual bool FetchSilhouetteImage() = 0;

	void set_world2camera_pose(const Pose& world2camera_pose);
	void set_camera2world_pose(const Pose& camera2world_pose);

	const cv::Mat& normal_image() const;
	const cv::Mat& silhouette_image() const;
	const cv::Mat& depth_image() const;

	Intrinsics intrinsics() const { return intrinsics_; }

protected:
	void ClearDepthImage();
	void ClearSilhouetteImage();
	void ClearNormalImage();

	cv::Mat depth_image_{};
	cv::Mat normal_image_{};
	cv::Mat silhouette_image_{};

	Pose world2camera_pose_{Pose::Identity()};
	Pose camera2world_pose_{Pose::Identity()};

	Intrinsics intrinsics_{};

	std::mutex mutex_;
};